﻿using Company.Core.Attributes;
using Company.Core.Helpers;
using Company.Core.Models;
using Company.Logger;
using MvCamCtrl.NET;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace Company.Hardware.Camera.HIK
{
    /// <summary>
    /// 海康相机实现类
    /// 1.安装海康相机 MVS 软件，官网下载：https://www.hikrobotics.com/cn/machinevision/service/download/?module=0
    /// 2.找到安装目录下的 C:\....\MVS\Development\DotNet\{AnyCpu/x64/x32}\MvCameraControl.Net.dll
    /// 3.Net6.0默认AnyCpu，所有引用AnyCpu下的MvCameraControl.Net.dll
    /// </summary>
    [ExposedService(interfaces: typeof(ICamera))]
    class HIKCamera : CameraBase
    {
        private MyCamera _camera;
        private MyCamera.cbOutputExdelegate _callback; // 拍照后回调委托

        /// <summary>
        /// 初始化海康相机
        /// </summary>
        /// <returns></returns>
        public override bool DoInitialize()
        {
            int result = -1;

            // 查找设备
            if (!FindDevice(out MyCamera.MV_CC_DEVICE_INFO device))
            {
                Logs.LogError($"查找海康相机失败:{result}");
                return false;
            }

            // 创建设备
            if (_camera == null) _camera = new MyCamera();
            result = _camera.MV_CC_CreateDevice_NET(ref device);

            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"创建海康相机失败:{result}");
                return false;
            }

            // 打开相机
            result = _camera.MV_CC_OpenDevice_NET();
            if (result != MyCamera.MV_OK)
            {
                _camera.MV_CC_DestroyDevice_NET(); // 销毁相机
                Logs.LogError($"打开海康相机失败:{result}");
                return false;
            }

            // 设置相机数据包大小
            if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) // GigE相机（千兆以太网相机）
            {
                int packetSize = _camera.MV_CC_GetOptimalPacketSize_NET(); // 获取最优的网络数据包大小
                if (packetSize > 0)
                {
                    // 设置合适的数据包大小，用于提高网络传输图像的效率和稳定性
                    result = _camera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)packetSize);
                    if (result != MyCamera.MV_OK)
                    {
                        Logs.LogError($"海康相机数据包大小设置失败:{result}");
                        return false;
                    }
                }
                else
                {
                    Logs.LogError($"获取海康相机数据包大小失败:{result}");
                    return false;
                }
            }

            // 设置触发模式
            result = _camera.MV_CC_SetEnumValue_NET("TriggerMode", 1); // 开启触发模式
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机开启触发模式失败:{result}");
                return false;
            }

            result = _camera.MV_CC_SetEnumValueByString_NET("TriggerSource", "Software"); // 设置为软触发
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机设置软触发失败:{result}");
                return false;
            }

            // 设置回调
            _callback = new MyCamera.cbOutputExdelegate(OnCallback); // 创建回调函数
            result = _camera.MV_CC_RegisterImageCallBackEx_NET(_callback, IntPtr.Zero);//开启回调
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机开启回调失败:{result}");
                return false;
            }

            // 开始连续采集
            result = _camera.MV_CC_StartGrabbing_NET(); // 图像会不断从相机传输到主机缓冲区
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机开启抓图失败:{result}");
                return false;
            }

            return true;

        }

        /// <summary>
        /// 触发拍照
        /// </summary>
        /// <returns></returns>
        public override bool DoTrigger()
        {
            int result = -1;
            result = _camera.MV_CC_SetCommandValue_NET("TriggerSoftware"); // 软触发
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机软触发失败:{result}");
                return false;
            }

            return true;
        }

        /// <summary>
        /// 关闭相机
        /// </summary>
        /// <returns></returns>
        public override bool DoClose()
        {
            int result = -1;

            // 停止抓图
            result = _camera.MV_CC_StopGrabbing_NET();
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机停止抓图失败:{result}");
                return false;
            }

            // 关闭相机
            result = _camera.MV_CC_CloseDevice_NET();
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机关闭相机失败:{result}");
                return false;
            }

            // 销毁相机
            result = _camera.MV_CC_DestroyDevice_NET();
            if (result != MyCamera.MV_OK)
            {
                Logs.LogError($"海康相机销毁相机失败:{result}");
                return false;
            }

            return true;
        }

        /// <summary>
        /// 查找设备
        /// </summary>
        /// <param name="device"></param>
        /// <returns></returns>
        private bool FindDevice(out MyCamera.MV_CC_DEVICE_INFO device)
        {
            device = default;
            MyCamera.MV_CC_DEVICE_INFO_LIST list = default;
            int result = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref list);
            if (result != 0)
            {
                return false;
            }

            if (list.nDeviceNum <= 0)
            {
                return false;
            }

            device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(list.pDeviceInfo[0], typeof(MyCamera.MV_CC_DEVICE_INFO_LIST));
            return true;
        }

        /// <summary>
        /// 相机回调函数
        /// </summary>
        /// <param name="pData"></param>
        /// <param name="pFrameInfo"></param>
        /// <param name="pUser"></param>
        private void OnCallback(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            /**
             * 
               if (_bufferBGRA == null)
               {
                   _bufferBGRA = new UnmanagedArray2D<ColorBGRA>(pFrameInfo.nWidth, pFrameInfo.nHeight);
               }

               // todo 确认厂家提供的相机的数据格式，有必要的时候需要进行图像数据转换
               MemoryHelper.CopyMemory(_bufferBGRA.IntPtr, pData, _bufferBGRA.Size);
               TriggerCallback(new CameraImage(_bufferBGRA)); // 回传图像
            */

            /**byte[] rawData = new byte[pFrameInfo.nFrameLen];
            Marshal.Copy(pData, rawData, 0, (int)pFrameInfo.nFrameLen);*/

            switch (pFrameInfo.enPixelType)
            {
                // 1. 单色（Mono）格式
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8: // 8位灰度（1字节/像素）
                    //ProcessMono8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10: // 10位灰度（存储为16位，高位有效）
                    //ProcessMono10(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12: // 12位灰度（存储为16位，高位有效）
                    //ProcessMono12(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono16: // 16位灰度（2字节/像素）
                    //ProcessMono16(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                // 2. Bayer RAW 格式（需去马赛克）
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8: // Bayer GRBG 8位
                    //ProcessBayerGR8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8: // Bayer RGGB 8位
                    //ProcessBayerRG8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8: // Bayer GBGR 8位
                    //ProcessBayerGB8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8: // Bayer BGGR 8位
                    //ProcessBayerBG8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                // 3. RGB/BGR 格式
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed: // 24位RGB（R-G-B顺序）
                    //ProcessRGB8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed: // 24位BGR（B-G-R顺序，OpenCV默认）
                    //ProcessBGR8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGBA8_Packed: // 32位RGBA（带Alpha通道）
                    //ProcessRGBA8(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    ProcessRGBA8(pData, ref pFrameInfo, pUser);
                    break;

                // 4. YUV 格式
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed: // YUV422通用格式
                    //ProcessYUV422(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed: // YUV422（YUYV打包格式）
                    //ProcessYUYV(rawData, pFrameInfo.nWidth, pFrameInfo.nHeight);
                    break;

                // 5. 其他特殊格式
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Coord3D_ABC32f: // 3D点云（float ABC坐标）
                    //ProcessCoord3D_ABC32f(rawData, pFrameInfo);
                    break;

                default:
                    Logs.LogError($"不支持的像素类型: {pFrameInfo.enPixelType}");
                    break;
            }
        }

        private void ProcessRGBA8(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            var bufferBGRA = new UnmanagedArray2D<ColorBGRA>(pFrameInfo.nWidth, pFrameInfo.nHeight);
            MemoryHelper.CopyMemory(bufferBGRA.IntPtr, pData, bufferBGRA.Size);

            /**
            // 保存图像
            Bitmap bitmap = new Bitmap(bufferBGRA.Width
                , bufferBGRA.Height
                , bufferBGRA.Stride
                , System.Drawing.Imaging.PixelFormat.Format32bppArgb
                , bufferBGRA.IntPtr
                );
            string fileName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".png";
            bitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
            */

            TriggerCallback(new CameraImage<ColorBGRA>(bufferBGRA)); // 回传图像
        }
    }
}
